home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / ease-3.5 / src / strops.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-15  |  16.7 KB  |  584 lines

  1. #ifdef FLUKE
  2. # ifndef LINT
  3.     static char RCSid[] = "@(#)FLUKE  $Header: /home/kreskin/u0/barnett/Src/Ease/ease/src/RCS/strops.c,v 3.4 1991/10/15 17:02:04 barnett Exp $";
  4. # endif LINT
  5. #endif FLUKE
  6.  
  7. /*
  8.  *    strops.c   -- Contains string operation routines used for constructing
  9.  *              definitions in cf format.
  10.  *
  11.  *    author       -- James S. Schoner, Purdue University Computing Center,
  12.  *                        West Lafayette, Indiana  47907
  13.  *
  14.  *    date       -- July 9, 1985
  15.  *
  16.  *    Copyright (c) 1985 by Purdue Research Foundation
  17.  *
  18.  *    All rights reserved.
  19.  *
  20.  * $Log: strops.c,v $
  21.  * Revision 3.4  1991/10/15  17:02:04  barnett
  22.  * Detect if (one_or_more) next ($2) error
  23.  *
  24.  * Revision 3.3  1991/09/09  16:33:23  barnett
  25.  * Minor bug fix release
  26.  *
  27.  * Revision 3.2  1991/05/16  10:45:25  barnett
  28.  * Better support for System V machines
  29.  * Support for machines with read only text segments
  30.  *
  31.  * Revision 3.1  1991/02/25  22:09:52  barnett
  32.  * Fixed some portability problems
  33.  *
  34.  * Revision 3.0  1991/02/22  18:50:27  barnett
  35.  * Added support for HP/UX and IDA sendmail.
  36.  *
  37.  * Revision 2.1  1990/01/30  15:52:55  jeff
  38.  * Added SunOS/Ultrix/IDA extensions  Jan 24, 1989 Bruce Barnett
  39.  *
  40.  * Revision 2.0  88/06/15  14:42:55  root
  41.  * Baseline release for net posting. ADR.
  42.  */
  43.  
  44. #include "fixstrings.h"
  45. #include <stdio.h>
  46. #include <strings.h>
  47. #include <ctype.h>
  48. #include "symtab.h"
  49.  
  50. #define MAXTOKPOS   99        /* maximum number of token positions */
  51. #define MAXNAME        1024    /* maximum length of an identifier   */
  52.  
  53. extern struct he *LookupSymbol ();
  54. extern char       MakeMac ();
  55. extern void      FatalError (),
  56.           PrintError (),
  57.           ErrorReport ();
  58. extern char *      malloc ();
  59.  
  60. short  Rformat = FALSE;            /* class read format flag      */
  61. short number_of_fields = 0;        /* number of fields on this line */
  62. #ifdef    DATA_RW
  63. static char   *Ptok   = "$  ";        /* positional token structure     */
  64. static char   *Cfield = "$= ";        /* class reference structure      */
  65. #else
  66. static char   *Ptok   = NULL;        /* positional token structure     */
  67. static char   *Cfield = NULL;        /* class reference structure      */
  68. #endif
  69. static char   *Ofield = "$-";        /* one token match structure      */
  70. static char   *Zfield = "$*";        /* zero or more tokens structure  */
  71. static char   *Pfield = "$+";        /* one or more tokens structure      */
  72.  
  73. /*
  74.  *  FLUKE jps 25-apr-86
  75.  *
  76.  *  Add the three new $%x, $%y, and $!x match operators that Sun introduced
  77.  *  with release 3.0.
  78.  */
  79.  
  80. #ifdef    DATA_RW
  81. static char   *Mfield = "$% ";        /*    match in specified YP map */
  82. static char   *Nfield = "$! ";        /* no match in specified YP map */
  83. static char   *Mtest  = "$? ";        /* conditional macro test string  */
  84. #else
  85. static char   *Mfield = NULL;        /*    match in specified YP map */
  86. static char   *Nfield = NULL;        /* no match in specified YP map */
  87. static char   *Mtest  = NULL;        /* conditional macro test string  */
  88. #endif
  89.  
  90. #ifndef    DATA_RW
  91. /* This section of code is for those machines with split text and data
  92.  * areas - where string constants are not modifiable
  93.  */
  94. #define nil (char *)0
  95.  
  96. char *      Strdup(string) /* a clone of the strdup() routine */
  97. char    *string;
  98. {
  99.     char *s;
  100.     s=malloc(strlen(string));
  101.     if (!s) return (nil);
  102.     (void) sprintf(s,"%s",string);
  103.     return (s);
  104. }
  105. void InitStrOps()
  106. {
  107.     if(!(Ptok = Strdup("$  ")) || !(Cfield = Strdup("$= ")) ||
  108.        !(Mfield = Strdup("$% ")) || !(Nfield = Strdup("$! ")) ||
  109.        !(Mtest = Strdup("$? ")))
  110.            FatalError("Out of memory in InitStrOps()", (char *)NULL);
  111. }
  112. #endif
  113.  
  114.  
  115. /*
  116.  *    ConvOpt () -- Convert an Ease option identifier (optid) by returning a
  117.  *              string representation of the cf format.  
  118.  *
  119.  */
  120. char *
  121. ConvOpt (optid) 
  122. register enum opts optid;
  123. {
  124.     switch (optid) {
  125.         case opt_A  :    return ("A");
  126.         case opt_a  :    return ("a");
  127.         case opt_B  :    return ("B");
  128.         case opt_b  :    return ("b");
  129.         case d_opt_b:    return ("b");
  130.         case opt_C  :    return ("C");
  131.         case opt_c  :    return ("c");
  132.         case opt_D  :    return ("D");
  133.         case opt_d  :    return ("d");
  134.         case opt_e  :
  135.         case e_opt_e:    return ("e");
  136.         case opt_F  :    return ("F");
  137.         case opt_f  :    return ("f");
  138.         case opt_g  :    return ("g");
  139.         case opt_h  :    return ("h");    /* SunOS Maxhops */
  140.         case opt_H  :    return ("H");
  141.         case opt_I  :   return ("I");    /* HP/UX */
  142.         case opt_i  :
  143.         case d_opt_i:    return ("i");
  144.         case opt_L  :    return ("L");
  145.         case opt_m  :
  146.         case e_opt_m:    return ("m");
  147.         case opt_N  :    return ("N");
  148.         case opt_n  :    return ("n");
  149.         case opt_o  :    return ("o");
  150.         case opt_P  :    return ("P");
  151.         case e_opt_p:    return ("p");
  152.         case opt_Q  :    return ("Q");
  153.         case opt_q  :    return ("q");
  154.         case d_opt_q:    return ("q");
  155.         case opt_r  :    return ("r");
  156.         case opt_R  :    return ("R");
  157.         case opt_S  :    return ("S");
  158.         case opt_s  :    return ("s");
  159.         case opt_T  :    return ("T");
  160.         case opt_t  :    return ("t");
  161.         case opt_u  :    return ("u");
  162.         case opt_v  :    return ("v");
  163.         case opt_W  :    return ("W");
  164.         case e_opt_w:    return ("w");
  165.         case opt_x  :    return ("x");
  166.         case opt_X  :    return ("X");
  167.         case opt_y  :    return ("y");
  168.         case opt_Y  :    return ("Y");
  169.         case opt_z  :    return ("z");
  170.         case opt_Z  :    return ("Z");
  171.         case e_opt_z:    return ("z");
  172.         case opt_SL  :    return ("/");
  173.         default     :    FatalError ("Bad case in ConvOpt ()", (char *) NULL);
  174.     }
  175.     /*NOTREACHED*/
  176. }
  177.  
  178.  
  179. /*
  180.  *    ConvFlg () -- Convert an Ease mailer flag identifier (flgid) by 
  181.  *              string representation of the cf format.  
  182.  *
  183.  */
  184. char *
  185. ConvFlg (flgid)
  186. register enum flgs flgid;    /* flag identifier */
  187. {
  188.     switch (flgid) {
  189.         case flg_f:    return ("f");
  190.         case flg_r:    return ("r");
  191.         case flg_S:    return ("S");
  192.         case flg_n:    return ("n");
  193.         case flg_l:    return ("l");
  194.         case flg_s:    return ("s");
  195.         case flg_m:    return ("m");
  196.         case flg_F:    return ("F");
  197.         case flg_D:    return ("D");
  198.         case flg_M:    return ("M");
  199.         case flg_x:    return ("x");
  200.         case flg_P:    return ("P");
  201.         case flg_u:    return ("u");
  202.         case flg_h:    return ("h");
  203.         case flg_H:    return ("H");
  204.         case flg_A:    return ("A");
  205.         case flg_U:    return ("U");
  206.         case flg_e:    return ("e");
  207.         case flg_X:    return ("X");
  208.         case flg_L:    return ("L");
  209.         case flg_p:    return ("p");
  210.         case flg_I:    return ("I");
  211.         case flg_C:    return ("C");
  212.         case flg_E:    return ("E");
  213.         case flg_R:    return ("R");
  214.         case flg_V:    return ("V");    /* IDA */
  215.         case flg_B:    return ("B");    /* IDA */
  216.         default   :    FatalError ("Bad case in ConvFlg ()", (char *) NULL);
  217.     }
  218.     /*NOTREACHED*/
  219. }
  220.  
  221.  
  222. /*
  223.  *    ConvMat () -- Convert an Ease mailer attribute (mat) by returning a
  224.  *              string representation of the cf format.  
  225.  *
  226.  */
  227. char *
  228. ConvMat (mat)
  229. register enum mats mat;        /* mailer attribute flag */
  230. {
  231.     switch (mat) {
  232.         case mat_path        : return ("P");
  233.         case mat_flags        : return ("F");
  234.         case mat_sender        : return ("S");
  235.         case mat_recipient    : return ("R");
  236.         case mat_argv        : return ("A");
  237.         case mat_eol        : return ("E");
  238.         case mat_maxsize    : return ("M");
  239.         default            : FatalError ("Bad case in ConvMat ()", (char *) NULL);
  240.     }
  241.     /*NOTREACHED*/
  242. }
  243.  
  244.  
  245. /*
  246.  *    MacScan () -- Scan a string (pstring) for macros, replacing the Ease
  247.  *              form with the one-character form required by cf format.
  248.  *
  249.  */
  250. char *
  251. MacScan (pstring)
  252. char *pstring;        /* macro expandable string */
  253. {
  254.     register char *searchptr;    /* string search pointer     */
  255.     register char *bptr, *eptr;    /* macro begin and end pointers */
  256.     char macname [MAXNAME];        /* macro name buffer        */
  257.     int    quote = 0;            /* flag for detecting a quote() function */
  258.  
  259.     if ((searchptr = pstring) == NULL)
  260.         return ((char *) NULL);
  261.     while (*searchptr != '\0')     /* find and rewrite all macros  */
  262.         if (*searchptr == '\\') {
  263.             searchptr = searchptr + 2;
  264.             continue;
  265.         } else if (*searchptr++ == '$') {
  266.             if (*searchptr == '{') {
  267.             if (sscanf (searchptr + 1, "quote(%[^)])", macname) == 1) {
  268.                 /* a quote(macro) sequence */
  269.                     quote++;
  270.             } else if (sscanf (searchptr + 1, "%[^}]", macname) != 1) {
  271.                 PrintError ("Invalid macro format: %s", searchptr + 1);
  272.                 return ((char *) NULL);
  273.             } 
  274.             if (quote) {
  275.                 quote=0;
  276.                 *searchptr++='!'; /* insert a quote */
  277.                 /* insert the macro letter */
  278.                 *searchptr++ = MakeMac (LookupSymbol (macname),
  279.                             (unsigned) ID_MACRO);
  280.                 /* now looking at quote(   */
  281.                 /* must skip over everything until )}, and then rewrite
  282.                    the rest of the macro */
  283.                 bptr = eptr = searchptr; 
  284.                 while (*eptr && *eptr != ')') /* skip to quote */
  285.                   eptr++;
  286.                 while (*eptr && *eptr != '}') /* skip past } */
  287.                   eptr++;
  288.                 eptr++;
  289.                 do    /* copy everything from eptr to end of line */
  290.                   *bptr++ = *eptr;
  291.                 while (*eptr++ != '\0');
  292.             } else {
  293.                 *searchptr++ = MakeMac (LookupSymbol (macname),
  294.                             (unsigned) ID_MACRO);
  295.                 bptr = eptr = searchptr;
  296.                 while (*eptr++ != '}')    /* delete until end of {name} */
  297.                   /* empty */ ;
  298.                 do    /* copy rest of line */
  299.                   *bptr++ = *eptr;
  300.                 while (*eptr++ != '\0');
  301.             }
  302.             } else if (isupper(*searchptr)){ /* $ not followed by { */
  303.             /* macro name might be one character */
  304.             /* but or might be more than one.    */
  305.             if (sscanf (searchptr, "%[A-Z]", macname) != 1) {
  306.                 PrintError ("Invalid macro format: %s", searchptr + 1);
  307.                 return ((char *) NULL);
  308.             } 
  309.             *searchptr++ = MakeMac (LookupSymbol (macname),
  310.                         (unsigned) ID_MACRO);
  311.             bptr = eptr = searchptr;
  312.             while (isupper(*eptr))    /* delete old macro chars */
  313.                 eptr++;
  314.             do
  315.                 *bptr++ = *eptr;
  316.             while (*eptr++ != '\0');
  317.             } 
  318.         } /* end of (if char == '$' ) */
  319.     return (pstring);
  320. }
  321.  
  322.  
  323. /*
  324.  *    MakeRStr () -- Construct and return a pointer to a class read string 
  325.  *               using the filename fname and read format rformat.  
  326.  *
  327.  */
  328. char *
  329. MakeRStr (fname, rformat)
  330. char *fname,            /* file name for class read */
  331.      *rformat;            /* format for class read    */
  332. {
  333.     register char *res;    /* resultant read string    */
  334.  
  335.     Rformat = TRUE;        /* set read format flag     */
  336.     if (rformat == NULL)
  337.         return (fname);
  338.     res = (char *) realloc (fname, strlen (fname) + strlen (rformat) + 2);
  339.     if (res == NULL)
  340.         FatalError ("System out of string space in MakeRStr ()", (char *) NULL);
  341.     res = strcat (res, " ");    /* construct read string */
  342.     res = strcat (res, rformat);
  343.     free (rformat);
  344.     return (res);
  345. }
  346.  
  347.  
  348. /*
  349.  *    ListAppend () -- Append string list2 to string list1 using the 
  350.  *             separator sep.  A pointer to the newly constructed
  351.  *             string is returned.
  352.  *
  353.  */
  354. char *
  355. ListAppend (list1, list2, sep)
  356. char *list1,            /* first string     */
  357.      *list2,            /* second string      */
  358.      *sep;            /* string separator    */
  359. {
  360.     register char *res;    /* resultant string    */
  361.  
  362.     res = (char *) malloc (strlen (list1) + strlen (list2) + strlen (sep) + 1);
  363.     if (res == NULL)
  364.         FatalError ("System out of string space in ListAppend ()", (char *) NULL);
  365.     res = strcpy (res, list1);
  366.     if (list1 != NULL)    /* use separator if first string not null */
  367.         res = strcat (res, sep);
  368.     res = strcat (res, list2);
  369.     return (res);
  370. }
  371.  
  372.  
  373. /*
  374.  *    MakeCond () -- Construct a macro conditional string in cf format.  The
  375.  *               conditional is based on the macro testmac, with an "if
  376.  *               set" result ifstring, which may contain an optional 
  377.  *               "if not set" result string appended to it.
  378.  *
  379.  */
  380. char *
  381. MakeCond (testmac, ifstring)
  382. struct he *testmac;        /* macro for conditional testing          */
  383. char       *ifstring;         /* "if macro set" result string(s)           */
  384. {
  385.     register char *res;    /* resultant conditional string             */
  386.  
  387.     Mtest[2] = MakeMac (testmac, (unsigned) ID_MACRO); /* get one-char macro rep */
  388.     res = (char *) malloc (strlen (ifstring) + 6);
  389.     if (res == NULL)
  390.         FatalError ("System out of string space in MakeCond ()", (char *) NULL);
  391.     res = strcpy (res, Mtest);
  392.     res = strcat (res, ifstring);        /* build result part      */
  393.     res = strcat (res, "$.");        /* end of conditional     */
  394.     free (ifstring);
  395.     return (res);
  396. }
  397.  
  398.  
  399. /*
  400.  *    MakePosTok () -- Construct and return a positional token string 
  401.  *             representation from the parameter num.
  402.  *
  403.  */
  404. char *
  405. MakePosTok (num)
  406. register int num;            /* numerical value of positional token */
  407. {
  408.     char buf[100];
  409.     if (num > MAXTOKPOS) {
  410.         ErrorReport ("Positional token too large.\n");
  411.         return ((char *) NULL);
  412.     } else {
  413.         if (num > number_of_fields) {
  414.         sprintf(buf," $%d used in right hand side of rule, but maximum positional parameter is %d\n", num, number_of_fields);
  415.         ErrorReport(buf);
  416.         }
  417.         if (num > 9) {    /* two-digit positional token */
  418.             Ptok[1] = '0' + (num / 10);
  419.             Ptok[2] = '0' + (num % 10);
  420.             Ptok[3] = '\0';
  421.         } else {
  422.             Ptok[1] = '0' + num;
  423.             Ptok[2] = '\0';
  424.         }
  425.     return (Ptok);
  426.     }
  427. }
  428.  
  429.  
  430. /*
  431.  *    Bracket () -- Construct and return a cf string form of the 
  432.  *              canonicalization of the string identifier passed in
  433.  *              the string parameter psb if dflag is true, else
  434.  *              simply bracket the identifier without dollar signs
  435.  *              for numeric hostname specifications.
  436.  *
  437.  */
  438. char *
  439. Bracket (psb, dflag)
  440. char *psb;            /* identifier to be canonicalized */
  441. short dflag;            /* dollar flag               */
  442. {
  443.     register char *res;    /* resultant cf form           */
  444.     register short extra;    /* extra space needed for malloc  */
  445.     
  446.     extra = dflag ? 5 : 3;
  447.     res = (char *) malloc (strlen (psb) + extra);
  448.     if (res == NULL)
  449.         FatalError ("System out of string space in Bracket ()", (char *) NULL);
  450.     if (dflag)
  451.         res = strcpy (res, "$[");
  452.     else
  453.         res = strcpy (res, "[");
  454.     res = strcat (res, psb);
  455.     if (dflag)
  456.         res = strcat (res, "$");
  457.     res = strcat (res, "]");
  458.     return (res);
  459. }
  460. /*
  461.  *    DbmParen () -- Construct and return a cf string form of the 
  462.  *              dbm reference of the IDA database identifier passed in
  463.  *              the string parameter db_psb, looking up the string identifier
  464.  *              passed in the string parameter lup_psb.
  465.  *
  466.  */
  467. char *
  468. DbmParen (db_psb, lup_psb)
  469. char *db_psb;            /* identifier of data base */
  470. char *lup_psb;            /* identifier being looked up */
  471. {
  472.     register char *res;    /* resultant cf form           */
  473.     
  474.     res = (char *) malloc (strlen (lup_psb) + 7);
  475.     if (res == NULL)
  476.         FatalError ("System out of string space in DbmParen ()", (char *) NULL);
  477.     res = strcpy (res, "$(x ");
  478.     *(res+2) = *db_psb;
  479.     res = strcat (res, lup_psb);
  480.     res = strcat (res, " $)");
  481.     return (res);
  482. }
  483.  
  484.  
  485. /*
  486.  *    MakeRSCall () -- Construct and return a cf string form of a call
  487.  *             to a ruleset (cid), which would pass to it the
  488.  *             remainder of a rewriting address (rwaddr).
  489.  *
  490.  */
  491. char *
  492. MakeRSCall (cid, rwaddr)
  493. register struct he *cid;    /* called ruleset identifier         */
  494. register char *rwaddr;        /* remainder of rewriting address    */
  495. {
  496.     register char *res;    /* resultant cf string for the call  */
  497.     
  498.     if (!ISRULESET(cid->idtype)) {    /* check validity of ruleset */
  499.         PrintError ("Undefined ruleset identifier: %s", cid->psb);
  500.         return ((char *) NULL);
  501.     }
  502.     /*
  503.      * FLUKE jps - 8-may-86 - boost string size by 1 to accomodate space
  504.      * character.
  505.      */
  506.     res = (char *) malloc (strlen (cid->idval.rsn) + strlen (rwaddr) + 4);
  507.     if (res == NULL)
  508.         FatalError ("System out of string space in MakeRSCall ()", (char *) NULL);
  509.     res = strcpy (res, "$>");    /* construct the call string */
  510.     res = strcat (res, cid->idval.rsn);
  511.     res = strcat (res, " ");  /* FLUKE jps - work around sendmail bug:
  512.                    * whitespace is needed to separate tokens:
  513.                    * for example:  $>30$D will confuse
  514.                    * sendmail, but $>30 $D is OK.
  515.                    */
  516.     res = strcat (res, rwaddr);
  517.     return (res);
  518. }
  519.  
  520.  
  521. /*
  522.  *    MakeField () -- Construct and return the cf string format for a
  523.  *            field variable.  The match count (count), an optional
  524.  *            class (class), and a match repetition flag (fstar)
  525.  *            are used to determine what type of field string to
  526.  *            construct.
  527.  *
  528.  *  FLUKE jps 25-apr-86 - Modified to add a fourth parameter "isYPmap".  This
  529.  *  supports Sun's new Yellow Pages match patterns added in release 3.0.
  530.  *
  531.  */
  532. char *
  533.     MakeField (count, class, fstar, isYPmap)
  534. register int count;        /* match count (0 or 1) */
  535. register struct he *class;    /* optional class type  */
  536. register short fstar;        /* repetition flag    */
  537. register short isYPmap;        /* "class" name is really a YP map name */
  538. {
  539.     switch (count) {
  540.         case 0:      if (class == NULL)    /* any token is valid */
  541.                 if (fstar)
  542.                     return (Zfield);
  543.                 else {
  544.                     ErrorReport ("Invalid field type.\n");
  545.                     return ((char *) NULL);
  546.                 }
  547.               else {        /* match 0 from class or map */
  548.                 if (isYPmap) {
  549.                     /*  "class" is a misnomer here; it's really
  550.                      *  a simple macro name for a YP map.
  551.                      *  FLUKE jps 25-apr-86
  552.                      */
  553.                     Nfield[2] = MakeMac (class, (unsigned) ID_MACRO);
  554.                     return (Nfield);
  555.                 } else {
  556.                 Cfield[1] = '~';
  557.                 Cfield[2] = MakeMac (class, (unsigned) ID_CLASS);
  558.                 return (Cfield);
  559.               }
  560.               }
  561.         case 1:      if (class == NULL)    /* any token is valid */
  562.                 if (fstar)
  563.                     return (Pfield);
  564.                 else
  565.                     return (Ofield);
  566.               else {        /* match 1 from class or map */
  567.                 if (isYPmap) {
  568.                     /*  "class" is a misnomer here; it's really
  569.                      *  a simple macro name for a YP map.
  570.                      *  FLUKE jps 25-apr-86
  571.                      */
  572.                     Mfield[2] = MakeMac (class, (unsigned) ID_MACRO);
  573.                     return (Mfield);
  574.                 } else {
  575.                 Cfield[1] = '=';
  576.                 Cfield[2] = MakeMac (class, (unsigned) ID_CLASS);
  577.                 return (Cfield);
  578.                 }
  579.               }
  580.         default:  ErrorReport ("Invalid field type.\n");
  581.     }
  582.     /*NOTREACHED*/
  583. }
  584.